package com.xiliu.server.modules.app.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiliu.common.constant.Constants;
import com.xiliu.common.result.R;
import com.xiliu.server.common.component.JwtToken;
import com.xiliu.server.common.security.entity.JwtUser;
import com.xiliu.server.common.security.service.MobileUserDetailsServiceImpl;
import com.xiliu.server.manager.AsyncManager;
import com.xiliu.server.manager.factory.AsyncFactory;
import com.xiliu.server.modules.app.vo.UserVo;
import com.xiliu.server.modules.ucenter.entity.XlUser;
import com.xiliu.server.modules.ucenter.service.XlUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xiliu
 * @date 2022/12/26 15:51
 */
@Api(tags = "移动端登录")
@RestController
@RequestMapping("/mobile")
@Slf4j
public class MobileLoginController {

    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private XlUserService userService;
    @Autowired
    private MobileUserDetailsServiceImpl memberUserDetailsService;
    @Autowired
    private JwtToken jwtTokenUtil;

    @ApiOperation("微信小程序登录")
    @ApiImplicitParam(name = "code",value = "前端授权登录后传来的code", required = true,paramType = "query")
    @PostMapping("login")
    public R doLogin(@RequestParam String code) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            //获取openId、unionid、session_key
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            XlUser user = userService.getOne(new LambdaQueryWrapper<XlUser>()
                    .eq(XlUser::getOpenId,sessionInfo.getOpenid())
                    .or()
                    .eq(XlUser::getUnionId,sessionInfo.getUnionid())
                    .eq(XlUser::getUserType,"2"),false);
            if (user != null) {
                // 已有用户
                if (user.getUserStatus() == 0) {
                    return R.error("您的账号已被禁用，请联系管理员");
                } else if (user.getUserStatus() == 2) {
                    return R.error("您的账号未验证，请联系管理员");
                } else {
                    // 更新登录时间
                    user.setLastLoginTime(new Date());
                    user.setUnionId(sessionInfo.getUnionid());
                    user.setUpdatedBy(Long.parseLong("0"));
                    userService.updateById(user);
                    UserVo vo = this.convertUserVo(user);
                    resultMap.put("token", this.createToken(sessionInfo.getOpenid()));
                    resultMap.put("userInfo", vo);
                    resultMap.put("sessionKey", sessionInfo.getSessionKey());
                    return R.ok(resultMap);
                }
            } else {
                // 注册
                user = new XlUser();
                user.setOpenId(sessionInfo.getOpenid());
                user.setUnionId(sessionInfo.getUnionid());
                user.setNums(1);
                user.setLastLoginTime(new Date());
                user.setUserType(2);
                user.setUserStatus(1);
                user.setUserLevel(1);
                user.setCreatedBy(Long.parseLong("0"));
                userService.save(user);
                UserVo vo = this.convertUserVo(user);
                resultMap.put("token", this.createToken(sessionInfo.getOpenid()));
                resultMap.put("userInfo", vo);
                resultMap.put("sessionKey", sessionInfo.getSessionKey());
                return R.ok(resultMap);
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }
    private UserVo convertUserVo(XlUser user) {
        UserVo vo = new UserVo();
        vo.setUserId(user.getUserId());
        vo.setAvatarUrl(user.getAvatar());
        vo.setNickName(user.getUserNickname());
        vo.setOpenId(user.getOpenId());
        vo.setMobile(user.getMobile());
        vo.setUserLevel(user.getUserLevel());
        return vo;
    }

    private String createToken(String openId) {
        String token = null;
        try {
            UserDetails userDetails = memberUserDetailsService.loadUserByOpenId(openId);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 登录成功记录日志
            AsyncManager.me().execute(AsyncFactory.recordLoginLog(openId, Constants.LOGIN_SUCCESS, "微信登录成功"));
            JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
            token = jwtTokenUtil.createToken(jwtUser);
        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
            // 登录失败记录日志
            AsyncManager.me().execute(AsyncFactory.recordLoginLog(openId, Constants.LOGIN_FAIL, e.getMessage()));
        }
        return token;
    }

    @ApiOperation("微信小程序登录授权")
    @ApiImplicitParam(name = "type",value = "授权类型  1:授权用户信息  2:授权手机号", required = true,paramType = "query")
    @PostMapping("login/authorization")
    public R authorization(@RequestParam String type, @RequestBody UserVo userVo) {
        if ("1".equals(type)) {
            // 授权用户信息
            XlUser user = userService.getById(userVo.getUserId());
            user.setAvatar(userVo.getAvatarUrl());
            user.setUserNickname(userVo.getNickName());
            user.setLastLoginTime(new Date());
            user.setUpdatedBy(Long.parseLong("0"));
            userService.updateById(user);
            userVo.setUserLevel(user.getUserLevel());
            return R.ok(userVo);
        } else if ("2".equals(type)) {
            // 授权手机号
            XlUser user = userService.getById(userVo.getUserId());
            userVo.setMobile(user.getMobile());
            return R.ok(userVo);
        }
        return R.ok(userVo);
    }
}
